package pers.luchuan.consumer.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import pers.luchuan.consumer.feign.ServiceProviderFeignClient;
import pers.luchuan.consumer.hystrix.ConsumerCommand;

@RestController
/**
 * @DefaultProperties: 指定此接口中公共的熔断设置
 * 如果在@DefaultProperties中指定了默认的降级方法
 * 则不需要在@HystrixCommand中单独指定了
 */
@DefaultProperties(defaultFallback = "defaultFallback")
public class ConsumerController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ServiceProviderFeignClient feignClient;

    /**
     * 基于ribbon的形式调用远程微服务（无降级）
     * 1.使用@LoadBalanced声明RestTemplate
     * 2.使用服务名称替换ip地址（负载均衡）
     */
    @GetMapping("/testRibbon/{id}")
    public String testRibbon(@PathVariable Long id) {
        return restTemplate.getForObject("http://service-provider/provider/"+id, String.class);
    }

    /**
     * 基于feign的形式调用远程微服务
     */
    @GetMapping("/testFeign/{id}")
    public String tesFeign(@PathVariable Long id) {
        return feignClient.test(id);
    }

    /**
     * 线程池隔离形式调用
     */
    @GetMapping("/testHystrix/{id}")
    public String testHystrix(@PathVariable Long id) {
        return new ConsumerCommand(restTemplate).execute();
    }

    /**
     * 基于hystrix注解方式实现服务熔断（针对restTemplate调用形式）
     */
    @HystrixCommand(fallbackMethod = "fallback")
    @GetMapping("/testHystrix2/{id}")
    public String testHystrix2(@PathVariable Long id) {
        return restTemplate.getForObject("http://service-provider/provider/"+id, String.class);
    }

    /**
     * 基于hystrix注解方式实现服务熔断（针对restTemplate调用形式，@HystrixCommand中没有指定降级方法则将采用defaultFallback）
     */
    @HystrixCommand
    @GetMapping("/testHystrix3/{id}")
    public String testHystrix3(@PathVariable Long id) {
        return restTemplate.getForObject("http://service-provider/provider/"+id, String.class);
    }

    private String fallback(Long id) {
        return "特定熔断降级";
    }

    /**
     * 统一降级方法中不能有参数
     * @return
     */
    private String defaultFallback() {
        return "统一熔断降级";
    }

    /**
     * consumer自己的服务（远程高并发调用其他服务（返回数据慢）时调用自己的服务也会受影响）
     */
    @GetMapping("test")
    public String test() {
        return "consumer data";
    }
}
